package com.bank.backend.boot.server.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.bank.backend.boot.base.constant.ExceptionConstant;
import com.bank.backend.boot.base.enums.TradeEnum;
import com.bank.backend.boot.base.model.dto.ModelDTO;
import com.bank.backend.boot.base.model.dto.ModelTradeDTO;
import com.bank.backend.boot.base.model.dto.TradeDTO;
import com.bank.backend.boot.base.model.dto.TradeQueryDTO;
import com.bank.backend.boot.base.model.dto.TradeQueryPageDTO;
import com.bank.backend.boot.base.model.entity.Account;
import com.bank.backend.boot.base.model.entity.Trade;
import com.bank.backend.boot.base.model.entity.User;
import com.bank.backend.boot.base.model.exception.GlobalException;
import com.bank.backend.boot.base.model.vo.PageVO;
import com.bank.backend.boot.base.model.vo.TradeInfoVO;
import com.bank.backend.boot.base.model.vo.TradeUAVO;
import com.bank.backend.boot.server.converter.TradeInfoConverter;
import com.bank.backend.boot.server.kafka.ProducerKafka;
import com.bank.backend.boot.server.mapper.AccountMapper;
import com.bank.backend.boot.server.mapper.TradeMapper;
import com.bank.backend.boot.server.mapper.UserMapper;
import com.bank.backend.boot.server.service.TradeService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
* @author JiaoWei
* @description 针对表【trade(交易表)】的数据库操作Service实现
* @createDate 2025-03-30 15:28:02
*/
@Service
@Slf4j
public class TradeServiceImpl extends ServiceImpl<TradeMapper, Trade>
    implements TradeService {

    @Resource
    private TradeMapper tradeMapper;

    @Resource
    private AccountMapper accountMapper;

    @Resource
    private UserMapper userMapper;

    @Resource
    private TradeInfoConverter tradeInfoConverter;

    @Resource
    private ProducerKafka producerKafka;

    /**
     * 保存交易信息
     * @param tradeDTO
     * @return
     */
    //TODO 修改为消息队列
    @Override
    public boolean saveTrade(TradeDTO tradeDTO) {
        if (tradeDTO.getSendAid() == tradeDTO.getReceiveAid()) {
            throw new GlobalException(ExceptionConstant.ACCOUNT_SAME);
        }

        Account sendAccound = accountMapper.selectById(tradeDTO.getSendAid());
        if (null == sendAccound) {
            throw new GlobalException(ExceptionConstant.SEND_ACCOUNT_NOT_EXIST);
        }

        Account receiveAccound = accountMapper.selectById(tradeDTO.getReceiveAid());
        if (null == receiveAccound) {
            throw new GlobalException(ExceptionConstant.RECEIVE_ACCOUNT_NOT_EXIST);
        }

        Trade converter = tradeInfoConverter.converter(tradeDTO);
        converter.setRisk(0);
        converter.setFinish(0);
        converter.setTradeTime(new Date());
        converter.setCreateTime(new Date());
        converter.setUpdateTime(new Date());
        int i = tradeMapper.insert(converter);
        if (i == 0) {
            return false;
        }
        return true;
    }

    /**
     * 根据账户id获取用户账户信息
     * @param aid
     * @return
     */
    private TradeUAVO getTradeUAVO(Long aid) {
        Account account = accountMapper.selectById(aid);
        User user = userMapper.selectById(account.getUid());
        TradeUAVO tradeUAVO = new TradeUAVO();
        tradeUAVO.setUid(user.getId());
        tradeUAVO.setName(user.getName());
        tradeUAVO.setPhone(user.getPhone());
        tradeUAVO.setNationality(user.getNationality());
        tradeUAVO.setAid(account.getId());
        tradeUAVO.setAccountNumber(account.getAccountNumber());
        tradeUAVO.setType(account.getType());
        tradeUAVO.setState(account.getState());
        return tradeUAVO;
    }

    /**
     * 获取交易信息
     * @param trade
     * @return
     */
    private TradeInfoVO getTradeInfoVO(Trade trade) {
        TradeInfoVO tradeInfoVO = tradeInfoConverter.convertInfo(trade);
        TradeUAVO sendTradeUAVO = getTradeUAVO(trade.getSendAid());
        TradeUAVO receiveTradeUAVO = getTradeUAVO(trade.getReceiveAid());
        tradeInfoVO.setSendAccount(sendTradeUAVO);
        tradeInfoVO.setReceiveAccount(receiveTradeUAVO);
        return tradeInfoVO;
    }

    /**
     * 根据id查询交易信息
     * @param id
     * @return
     */
    @Override
    public TradeInfoVO queryTradeById(Long id) {
        Trade trade = tradeMapper.selectById(id);
        if (null == trade) {
            return null;
        }
        TradeInfoVO tradeInfoVO = getTradeInfoVO(trade);
        return tradeInfoVO;
    }

    /**
     * 查询所有交易信息
     * @return
     */
    @Override
    public List<TradeInfoVO> queryTradeList() {
        List<Trade> trades = tradeMapper.selectList(null);
        if (CollectionUtils.isEmpty(trades)) {
            return null;
        }
        List<TradeInfoVO> tradeInfoVOS = new ArrayList<>();
        for (Trade trade : trades) {
            TradeInfoVO tradeInfoVO = getTradeInfoVO(trade);
            tradeInfoVOS.add(tradeInfoVO);
        }
        return CollectionUtil.reverse(tradeInfoVOS);
    }

    /**
     * 根据用户id查询交易信息
     *
     * @param uid
     * @return
     */
    @Override
    public List<TradeInfoVO> queryTradeListByUid(Long uid) {
        List<Account> accounts = accountMapper.queryAccountListByUid(uid);
        List<TradeInfoVO> tradeInfoVOS = new ArrayList<>();
        for (Account account : accounts) {
            QueryWrapper<Trade> wrapper = new QueryWrapper<>();
            wrapper.eq("send_aid", account.getId())
                    .or()
                    .eq("receive_aid", account.getId());
            List<Trade> trades = tradeMapper.selectList(wrapper);
            if (CollectionUtils.isEmpty(trades)) {
                return null;
            }
            for (Trade trade : trades) {
                TradeInfoVO tradeInfoVO = getTradeInfoVO(trade);
                tradeInfoVOS.add(tradeInfoVO);
            }
        }
        return tradeInfoVOS;
    }


    /**
     * 根据参数查询交易信息
     * @param tradeQueryDTO
     * @return
     */
    @Override
    public List<TradeInfoVO> queryTradeListByParam(TradeQueryDTO tradeQueryDTO) {
        QueryWrapper<Trade> wrapper = new QueryWrapper<>();
        wrapper.eq("send_aid", tradeQueryDTO.getAid())
                .or()
                .eq("receive_aid", tradeQueryDTO.getAid())
                .or()
                .eq("type", tradeQueryDTO.getType())
                .or()
                .eq("risk", tradeQueryDTO.getRisk())
                .or()
                .eq("finish", tradeQueryDTO.getFinish());

        List<Trade> trades = tradeMapper.selectList(wrapper);
        if (CollectionUtils.isEmpty(trades)) {
            return null;
        }
        List<TradeInfoVO> tradeInfoVOS = new ArrayList<>();
        for (Trade trade : trades) {
            TradeInfoVO tradeInfoVO = getTradeInfoVO(trade);
            tradeInfoVOS.add(tradeInfoVO);
        }
        return tradeInfoVOS;
    }

    @Override
    public PageVO<TradeInfoVO> queryManualPage(int current, int pageSize) {
        int offset = (current - 1) * pageSize;
        List<Trade> tradePageVO = tradeMapper.queryManualPage(offset, pageSize);
        if (CollectionUtils.isEmpty(tradePageVO)) {
            return new PageVO<>();
        }

        List<TradeInfoVO> tradeInfoVOS = new ArrayList<>();
        for (Trade trade : tradePageVO) {
            TradeInfoVO tradeInfoVO = getTradeInfoVO(trade);
            tradeInfoVOS.add(tradeInfoVO);
        }

        PageVO<TradeInfoVO> tradeInfoVOPageVO = new PageVO<>();
        tradeInfoVOPageVO.setRecords(tradeInfoVOS);
        tradeInfoVOPageVO.setTotal(tradeInfoVOS.size());
        return tradeInfoVOPageVO;
    }

    @Override
    public PageVO<TradeInfoVO> queryTradePage(TradeQueryPageDTO tradeQueryPageDTO) {
        int current = tradeQueryPageDTO.getCurrent();
        int pageSize = tradeQueryPageDTO.getPageSize();
        int offset = (current - 1) * pageSize;
        List<Trade> trades = tradeMapper.queryTradePage(pageSize, offset, tradeQueryPageDTO);
        if (CollectionUtils.isEmpty(trades)) {
            return null;
        }
        List<TradeInfoVO> tradeInfoVOS = new ArrayList<>();
        for (Trade trade : trades) {
            TradeInfoVO tradeInfoVO = getTradeInfoVO(trade);
            tradeInfoVOS.add(tradeInfoVO);
        }
        PageVO<TradeInfoVO> pageVO = new PageVO<>();
        pageVO.setRecords(tradeInfoVOS);
        pageVO.setTotal(tradeInfoVOS.size());
        return pageVO;
    }

    @Override
    public boolean modelTrade(ModelDTO modelDTO) {
        Trade trade = new Trade();
        trade.setSendAid(modelDTO.getSendAccount());
        trade.setReceiveAid(modelDTO.getReceiveAccount());
        trade.setAmount(modelDTO.getTransactionAmount());
        trade.setTradeTime(new Date());
        trade.setFinishTime(null);
        TradeEnum tradeEnum = TradeEnum.getByDesc(modelDTO.getTransactionType());
        trade.setType(tradeEnum.getCode());
        trade.setLocation(modelDTO.getTransactionLocation());
        trade.setEquipment(modelDTO.getDeviceType());
        trade.setRisk(TradeEnum.RISK_0.getCode());
        trade.setFinish(TradeEnum.Finish_0.getCode());
        trade.setCreateTime(new Date());
        trade.setUpdateTime(new Date());
        int i = tradeMapper.insert(trade);
        if (i != 0) {
//            detectFraud(modelDTO, trade);
            ModelTradeDTO modelTradeDTO = new ModelTradeDTO();
            modelTradeDTO.setModelDTO(modelDTO);
            modelTradeDTO.setTrade(trade);
            producerKafka.send("bank-backend-identify", JSON.toJSONString(modelTradeDTO));
        }
        return i != 0;
    }

//    private void detectFraud(ModelDTO modelDTO, Trade trade) {
//        ModelVO modelVO = new ModelVO();
//        modelVO.setCustomerId(String.valueOf(trade.getId()));
//        modelVO.setGender(modelDTO.getGender());
//        modelVO.setAge(modelDTO.getAge());
//        modelVO.setState(modelDTO.getState());
//        modelVO.setCity(modelDTO.getCity());
//        modelVO.setBankBranch(modelDTO.getBankBranch());
//        modelVO.setAccountType(modelDTO.getAccountType());
//        Date date = trade.getTradeTime();
//        SimpleDateFormat day = new SimpleDateFormat("dd-MM-yyyy");
//        String nowDay = day.format(new Date());
//        modelVO.setTransactionDate(nowDay);
//        SimpleDateFormat time = new SimpleDateFormat("HH:mm:ss");
//        String nowTime = time.format(new Date());
//        modelVO.setTransactionTime(nowTime);
//        modelVO.setTransactionAmount(modelDTO.getTransactionAmount());
//        modelVO.setMerchantId("*************");
//        modelVO.setTransactionType(modelDTO.getTransactionType());
//        modelVO.setMerchantCategory(modelDTO.getMerchantCategory());
//        modelVO.setAccountBalance(modelDTO.getAccountBalance());
//        modelVO.setTransactionDevice(modelDTO.getTransactionDevice());
//        modelVO.setTransactionLocation(modelDTO.getTransactionLocation());
//        modelVO.setDeviceType(modelDTO.getDeviceType());
//        modelVO.setTransactionDescription(modelDTO.getTransactionDescription());
//        log.warn("modelVO:{}", modelVO);
//        ModelResultDTO modelResultDTO = modelFeign.detectFraud(modelVO);
//        log.warn("modelResultDTO:{}", modelResultDTO);
//    }
}




